﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;

namespace Tensop.Net.Core
{
    [Flags]
    internal enum ConnectionContextOperation
    {
        Transmit =      0x00000000,
        ReceiveOp =     0x00000001,
        SendOp =        0x00000010,
        SendWaitOp =    0x00000100,
        Cache =         0x00001000,
    }
    public class ConnectionContext : IDisposable
    {
        /// <summary>
        /// 获取当前连接上下文的识别ID
        /// </summary>
        public int Id { get; internal set; }

        /// <summary>
        /// 获取当前连接上下文绑定的套接字地址
        /// </summary>
        /// <exception cref="NullReferenceException">当未连接客户端的时候将会触发空引用异常</exception>
        public EndPoint RemoteEndPoint { get => Client.RemoteEndPoint; }

        /// <summary>
        /// 获取或设置当前连接上下文绑定的自定义对象
        /// </summary>
        public object UserToken { get; set; }

        internal SocketAsyncEventArgs Reader { get; set; }
        internal SocketAsyncEventArgs Sender { get; set; }
        internal Socket Client { get; set; }

        internal List<byte> RecvBuffer { get; set; }
        internal List<byte> SendBuffer { get; set; }

        internal int ContentLength { get; set; }
        internal ConnectionContextOperation State { get; set; }

        EventHandler<SocketAsyncEventArgs>                          Handler;

        internal ConnectionContext(int id, EventHandler<SocketAsyncEventArgs> handler)
        {
            Handler = handler;
            Id = id;
            Reader = new SocketAsyncEventArgs() { UserToken = this };
            Sender = new SocketAsyncEventArgs() { UserToken = this };
            Reader.Completed += Handler;
            Sender.Completed += Handler;
            Reader.SetBuffer( new byte[4096], 0, 4096 );
            Sender.BufferList = new List<ArraySegment<byte>>();
            RecvBuffer = new List<byte>( 4096 );
            State = ConnectionContextOperation.Cache | ConnectionContextOperation.ReceiveOp;
        }

        public void Dispose()
        {
            if ( Client != null )
            {
                try
                {
                    Client.Shutdown( SocketShutdown.Both );
                }
                catch
                {

                }
                finally
                {
                    Client.Close();
                }
            }
            RecvBuffer.Clear();
            RecvBuffer = null;
            Reader.Dispose();
            Sender.Dispose();
            UserToken = null;
        }
    }
}
